package com.example.jetpack.flowTest

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
import kotlin.time.measureTime


// 1.协程是轻量级的线程，它们在某些 CoroutineScope 上下文中与 launch 协程构建器 一起启动
// 2.挂起函数： 不会造成线程阻塞，但是会挂起协程，并且只能在协程中使用

// GlobalScope.launch 后台启动一个新的协程 顶层协程
// runBlocking 是常规函数   coroutineScope是挂起函数

// 挂起 (挂起函数)
// 阻塞
// 非阻塞
// 等待作业
// 显示(非阻塞方式)
// 结构化并发：在执行操作所在的指定作用域内启动协程，而不是像通常使用线程（线程是全局的）安阳在GlobalScope启动
//      runBlocking协程构建器 将main函数转换为协程,其内的所有代码都在其作用域中，
// 其其内的每个协程构建器都将外部协程作用域添加到协程内其代码块所在的作用域内
//外部协程直到其作用域中启动的所有协程都执行完毕后才会结束
//      作用域构建器： 还可以声明自己的作用域，它会创建一个协程作用域 并且 在所有已启动的子协程执行完毕前不会结束
//协程取消

// 组合挂起函数：
// 默认顺序
// async并发
// 惰性 async
//  async 风格的函数
// 使用async 的结构化并发

//协程运行在以CoroutineContext类型为代表的上下文中 ，协程上下文是各种不同元素的集合
// 协程上下文包含  协程调度器（确定相关的协程在哪个线程或哪些线程上执行）：可以限制在特定的线程或分配到线程池或不受限制
// 默认的调度器 使用共享的后台线程池
// 非受限调度器和受限调度器


fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")

fun main_13() = runBlocking<Unit> {
    val a = async {
        log("I'm computing a piece of the answer")
        log("my job is ${coroutineContext[Job]}")
        6
    }
    val b = async {
        log("I'm computing another piece of the answer")
        7
    }

    log("The answer is ${a.await() * b.await()}")
}
/*

fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
fun main() = runBlocking<Unit> {
    // 运行在父协程的上下文中
//    launch {
//        log("a")
//    }
    val a = async {
        log("e")
        8
    }
    a.await()
    //不受限的-- 将工作在主线程中
//    launch(Dispatchers.Unconfined) {
//        log("b")
//    }
//    //默认调度器
//    launch(Dispatchers.Default) {
//        log("c")
//    }
//    //获得一个新的线程
//    launch(newSingleThreadContext("MyOwnThread")) {
//        log("d")
//    }

}
*/


suspend fun doSomethingOne(): Int {
    println("doSomethingOne --- a ")
//    delay(1000L)
    println("doSomethingOne --- b ")
    return 13
}

suspend fun doSomethingTwo(): Int {
    println("doSomethingTwo ----  a  ")
//    delay(1000)
    println("doSomethingTwo ----  b  ")
    return 29
}

fun main() = runBlocking {

    println("xxxxxxxxxx ")
    doSomethingOne()
    println("yyyyyyyyyy ")
    doSomethingTwo()
    println("zzzzzzzzz ")
}


suspend fun concurrentSum(): Int = coroutineScope {
    val one = async { doSomethingOne() }
    val two = async { doSomethingTwo() }
    one.await() + two.await()
}

//惰性启动async : job调用start 或者 await才会调用  发现 start比await效率高
fun main_12() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async(start = CoroutineStart.LAZY) { doSomethingOne() }
        val two = async(start = CoroutineStart.LAZY) { doSomethingTwo() }
        one.start()
        two.start()
//        one.await()
//        two.await()
        println("this answer is ${one.await() + two.await()}")
    }
    println("Completed in $time ms")
}

//并发调用挂起函数, 运行时间快了
fun main_11() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = async { doSomethingOne() }
        val two = async { doSomethingTwo() }
        println("this answer is ${one.await() + two.await()}")
    }
    println("Completed in $time ms")
}

//协程中顺序调用挂起函数
fun main_10() = runBlocking<Unit> {
    val time = measureTimeMillis {
        val one = doSomethingOne()
        val two = doSomethingTwo()
        println("this answer is ${one + two}")
    }
    println("Completed in $time ms")
}


var acquired = 0

class Resource {
    init {
        acquired++
    } // Acquire the resource

    fun close() {
        acquired--
    } // Release the resource
}

fun main_9() {
    runBlocking {
        repeat(100_000) { // Launch 100K coroutines
            launch {
                var resource: Resource? = null
                try {
                    withTimeout(101) {
                        delay(100)
                        resource = Resource()
                    }
                } finally {
                    resource?.close()
                }

//                val resource = withTimeout(101) { // Timeout of 60 ms
//                    delay(100) // Delay for 50 ms
//                    Resource() // Acquire a resource and return it from withTimeout block
//                }
//                resource.close() // Release the resource
            }
        }
    }
    // Outside of runBlocking all coroutines have completed
    println(acquired) // Print the number of resources still acquired
}


fun main_8() = runBlocking {
    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default) {
        var nextPrintTime = startTime
        var i = 0
//        while (i < 5){
        while (isActive) {
            if (System.currentTimeMillis() >= nextPrintTime) {
                println("job ,${i++}")
                nextPrintTime += 500L
            }
        }
    }
    delay(1300L)
//    println("main ")
    job.cancelAndJoin()
    println("main over ")
}


fun main_7() = runBlocking {
    val job = launch {
        repeat(100) {
            println("----------$it")
            delay(500)
        }
    }
    delay(1300)
//    job.cancel()    //取消作业
//    job.join() // 等待结束
    job.cancelAndJoin()     //取消作业并等待结束
    println("xxxxxxxx")
}


fun main_6() = runBlocking {
    GlobalScope.launch {
        repeat(1000) { i ->
            println("I'm sleeping $i ...")
            delay(500L)
        }
    }
//    delay(1300L) // 在延迟后退出
    println("xxxx")
}

fun main_5() = runBlocking {
    repeat(100000) {
        launch {
            delay(5000)
            println(it)
        }
    }
}


fun main_4() = runBlocking {
    launch {
        delay(200)
        println("2  Task from runBlocking")
    }

    //创建一个协程作用域，这个作用域里的内容执行完后才会向下执行
    coroutineScope {
        //创建一个新协程
        launch {
            delay(500L)
            println("3  Task from nested launch")
        }
        delay(100L)
        println("1  Task from coroutine scope")
    }

    //中间不加其他协程的情况下，此行先输出
//    println("Task from runBlocking first")

    launch {
        delay(300)
        println(".。。。。。。。。")
    }

    // 最后输出：
    println("4  Coroutine Scope is over")
}


fun main_3() = runBlocking {
    // 在 runBlocking作用域内启动了一个新协程
    launch {
        delay(1000)
        println("World")
    }
    println("Hello")
}

fun main_2() = runBlocking {
    val job = GlobalScope.launch {
        delay(1000)
        println("world")
    }
    println("Hello")
    //等待直到子协程执行结束  显示(非阻塞方式)等待
    //主协程与后台作业的持续时间没有任何关系了
    job.join()
}

fun main_1() = runBlocking {
    //在后台启动一个新的协程并继续
    GlobalScope.launch {
        delay(1000)  //非阻塞等待1秒
        println("World")
    }
    println("Hello,")
    delay(2000)
}

fun main_0() {
    //在后台启动一个新的协程并继续
    GlobalScope.launch {
        delay(1000)  //非阻塞等待1秒
        println("World")      //延迟后打印
    }
    println("Hello,")       //协程在等待时，主线程还在继续
    Thread.sleep(4000L)     //阻塞主线程2秒钟，保证JVM还活着
    println("运行完成")
    //runBlocking :
    runBlocking {
        //非阻塞函数，挂起主线程
        delay(1000)
    }
}


class CoroutinesTest {
}